<?php
namespace App\Services;

use App\Exceptions\PayException;
use App\Models\Order;
use App\Pay\Config\Config;
use App\Pay\Pay;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Session;

class PayService
{
    protected $notifyUrl;

    protected $returnUrl;

    public function pay(Order $order)
    {
        $gateway = $order->gateway;
        return $this->{$gateway}($order);
    }

    /**
     * 微信支付逻辑
     * @param Order $order
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     * @throws PayException
     */
    public function wxpay(Order $order)
    {
        $channel = $order->channel;
        $methods = $channel->method;
        $method = '';
        // 判断是否手机端
        if (is_mobile()) {
            if (in_array('h5', $methods)) {
                $method = 'h5';
            } else if (in_array('mini', $methods) && (!is_wechat_browser() || is_mini())) {
                $method = 'mini';
            } else if (in_array('mp', $methods)) {
                $method = 'mp';
            } else if (in_array('native', $methods)) {
                $method = 'native';
            }
        } else {
            if (in_array('native', $methods)) {
                $method = 'native';
            } else if (in_array('mp', $methods)) {
                $method = 'mp';
            } else if (in_array('mini', $methods)) {
                $method = 'mini';
            }
        }
        if (!$method) {
            throw new PayException('当前通道暂无可用支付方式');
        }

        // 判断如果选中公众号支付 并且当前环境并不是微信浏览器内只显示二维码
        if ('mp' === $method && !is_wechat_browser()) {
            // {debug:true, appId:'', timestamp:'', nonceStr:'', signature:'', jsApiList: ['chooseWXPay']}
            return view('pay.wechat.' . $method, compact('order', 'method'));
        }

        // 判断是否微信小程序 小程序如果是非 ajax请求则显示scheme二维码
        if ('mini' === $method && !request()->ajax()) {
            // 生成 url scheme 手机端使用url scheme
            if (is_mobile()) {
                $result = Cache::remember('mini:qrcode:urlscheme:' . $order->trade_no, 300, function () use($channel, $order) {
                    $miniAppService = new MiniAppService($channel->mini_appid, $channel->mini_secret);
                    return $miniAppService->getUrlScheme('pages/index/index', 'trade_no=' . $order->trade_no, true);
                });
                return view('pay.wechat.' . $method, compact('result', 'order', 'method'));
            } else {
                return redirect()->route('error.message')->withErrors('小程序暂不支持直接扫码');
            }

        }

        $params = [
            'out_trade_no' => $order->trade_no,
            'total_fee' => $order->total_amount * 100,
            'body' => '订单支付 - ' . $order->out_trade_no
        ];
        // 创建实例对象
        $wechatService = new WechatService($channel->mp_appid, $channel->mp_secret);
        // 如果是微信公众号支付需要获取openid
        // 如果是微信公众号支付 并且是微信浏览器内需要获取openid并且获取jssdk支付配置
        $jssdk = [];
        if ('mp' === $method && is_wechat_browser()) {
            $openid = Session::get('openid_' . md5($channel->id), null);
//            dd('openid_' . md5($channel->id));
//            dd(Session::all(), 'openid_' . md5($channel->id), $openid, Session::getId());
            $url = $wechatService->getSnsapiUrl(route('users.openid', ['channel' => $channel->id, 'callback' => route('pay', ['order' => $order->trade_no])]));
            if (is_null($openid)) return redirect($url)->send();
            $params['openid'] = $openid;
            $jssdk = $wechatService->getJssdkConfig();
        } else if ('mini' === $method) {
            $params['openid'] = $order->pay_user;
        }
        $result = Pay::wechat(new Config([
            'mch_id' => $channel->mch_id,
            'mch_key' => $channel->mch_key,
            'mp_appid' => $method === 'mini' ? $channel->mini_appid : $channel->mp_appid,
            'notify_url' => route('pay.notify', ['gateway' => Order::GATEWAY_WECHAT, 'channel' => $channel->id]),
        ]))->pay($method, $params);

        if ('mini' === $method) {
            return response()->json([
                'code' => 200,
                'message' => 'Success',
                'data' => [
                    'params' => $result
                ]
            ]);
        }
        return view('pay.wechat.' . $method, compact('result', 'order', 'jssdk', 'method'));
    }

    public function alipay(Order $order)
    {
        $channel = $order->channel;
        $methods = $channel->method;
        $method = '';
        // 判断是否手机端
        if (is_mobile() && in_array('wap', $methods)) {
            $method = 'wap';
        } else {
            if (in_array('scan', $methods)) {
                $method = 'scan';
            } else if (in_array('web', $methods)) {
                $method = 'web';
            }
        }
        if (!$method) {
            throw new PayException('当前通道暂无可用支付方式');
        }

        $params = [
            'out_trade_no' => $order->trade_no,
            'total_amount' => $order->total_amount,
            'subject' => '订单支付 - ' . $order->out_trade_no
        ];
        $result = Pay::alipay(new Config([
            'mch_id'      => $channel->mch_id,
            'public_key'  => $channel->public_key,
            'private_key' => $channel->private_key,
            'notify_url'  => route('pay.notify', ['gateway' => Order::GATEWAY_ALI, 'channel' => $channel->id]),
            'return_url'  => route('pay.return', ['gateway' => Order::GATEWAY_ALI, 'order' => $order->trade_no]),
        ]))->pay($method, $params);

        if ('wap' === $method || 'web' === $method) {
            return redirect($result);
        }

        return view('pay.alipay.' . $method, compact('result', 'order'));
    }

    public function qqpay(Order $order)
    {
        $channel = $order->channel;
        $methods = $channel->method;
        $method = '';
        if (in_array('native', $methods)) {
            $method = 'native';
        }
        if (!$method) {
            throw new PayException('当前通道暂无可用支付方式');
        }

        $params = [
            'out_trade_no' => $order->trade_no,
            'total_fee' => $order->total_amount * 100,
            'body' => '订单支付 - ' . $order->trade_no,
        ];

        $result = Pay::qqpay(new Config([
            'notify_url' => route('pay.notify', ['gateway' => Order::GATEWAY_QQ, 'channel' => $channel->id]),
            'mch_id' => $channel->mch_id,
            'mch_key' => $channel->mch_key
        ]))->pay($method, $params);

        return view('pay.qqpay.' . $method, compact('result', 'order'));
    }
}
